package com.skyworth.web.session.controller;

import com.skyworth.utils.CookieUtil;
import com.skyworth.web.admin.company.domain.CompanyModel;
import com.skyworth.web.admin.company.form.CompanyForm;
import com.skyworth.web.admin.company.service.CompanyService;
import com.skyworth.web.admin.role.service.RoleService;
import com.skyworth.web.admin.store.service.StoreService;
import com.skyworth.web.admin.user.domain.UserKind;
import com.skyworth.web.admin.user.domain.UserModel;
import com.skyworth.web.admin.user.form.UserForm;
import com.skyworth.web.admin.user.service.UserService;
import com.skyworth.web.common.Constants;
import com.skyworth.web.common.controller.BaseController;
import com.skyworth.web.shiro.ShiroRealmImpl;
import com.skyworth.web.wechat.common.MD5Encode;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.util.SavedRequest;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import static com.skyworth.web.common.Constants.COOKIE_USERNAME;

/**
 * Created by holin on 11/21/15.
 */

@Controller
public class SessionController extends BaseController {
	Logger LOG = LoggerFactory.getLogger(SessionController.class);

	@Autowired
	private UserService userService;

	@Autowired
	private RoleService roleService;

	@Autowired
	private StoreService storeService;

	@Autowired
	private CompanyService companyService;

	@RequestMapping(value={"/reg"},method = RequestMethod.GET)
	public String register() {
		return "session/register";
	}

	@RequestMapping(value = {"/register"}, method = RequestMethod.POST)
	public @ResponseBody
	Map<String, Object>  create(@ModelAttribute UserForm userForm,
								HttpSession session,
								Model model) {
		Map<String, Object> map = new HashMap<String, Object>();
		Map<String, Object> mapErr = new HashMap<String, Object>();

		boolean valid = true;
		String errorMsg=null;
		LOG.info("new user " + userForm.getUsername());

		if(userForm.getMobile()==null || userForm.getMobile().isEmpty()){
			errorMsg = "手机号码不能为空";
			valid = false;
		}else if(userForm.getUsername()==null || userForm.getUsername().isEmpty()){
			errorMsg = "用户名不能为空";
			valid = false;
		}
		else {
			if (userService.existsByUsername(userForm.username)) {
				errorMsg = "用户名：" + userForm.username + " 已注册";
				mapErr.put("username", errorMsg);
				valid = false;
			}
			if (userService.existsByMobile(userForm.getMobile())) {
				errorMsg = "手机号：" + userForm.getMobile() + " 已注册";
				mapErr.put("phoneNum", errorMsg);
				valid = false;
			}
			if (valid) {
				UserKind userKind =UserKind.ADMIN;
				userForm.kind = userKind.ordinal();
				UserModel user = userService.addUser(userForm);
				if (user != null) {
					if(!companyService.existByUser(user.getId())) {
						CompanyForm companyForm = new CompanyForm();
						companyForm.name = userForm.companyName;
						companyForm.appid = userForm.appid;
						companyForm.appsecret = userForm.appsecret;
						companyForm.ownerId = user.id;
						CompanyModel companyModel = companyService.addCompany(companyForm);

						if (null != companyModel) {
							user.setCompanyId(companyModel.getId());
							userService.updateUser(user);
						}
						model.addAttribute("company", companyModel);
					}else{
						valid = false;
						errorMsg="one user one company";
					}
				}
				if(valid) {
					map.put("url", "/admin/company");
					Subject currentUser = SecurityUtils.getSubject();
					UsernamePasswordToken token = new UsernamePasswordToken(userForm.username, MD5Encode.encode(userForm.password));
					currentUser.login(token);
					setUserSession(user);
					model.addAttribute("user", user);
				}
			}
		}
		map.put("valid", valid);
		map.put("errorMsg", errorMsg);
		map.put("errors", mapErr);
		return map;

	}

	//session login
	private boolean isSessionLogin() {
		UserModel userModel = currentUser();
		if (userModel != null) {
			LOG.info("session login user " + userModel.getUsername());
			return true;
		}
		return false;
	}
	//cookie login 
	private boolean isCookieLogin(HttpServletRequest request){
		String cookieUserName = null;
		try {
			cookieUserName = URLDecoder.decode(CookieUtil.getCookie(Constants.COOKIE_USER_KEY, request), "UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			LOG.error("get cookie error");
			return false;
		}

		if (cookieUserName != null && !"".equals(cookieUserName)) {
			String cookiePwd = CookieUtil.getCookie(Constants.COOKIE_PASSWORD_KEY, request);
			UsernamePasswordToken token = new UsernamePasswordToken(cookieUserName, cookiePwd);
			if(isLogin(token)){
				LOG.info("cookie login user "+cookieUserName);
				return true;
			}
		}
		return false;

	}

	@RequestMapping(value = {"/","/login"}, method = RequestMethod.GET)
	public String index(Model model, HttpServletRequest request) {
		String originUrl = "";
		SavedRequest savedRequest = WebUtils.getSavedRequest(request);
		if (savedRequest != null && savedRequest.getMethod().equalsIgnoreCase(AccessControlFilter.GET_METHOD)) {
			originUrl = savedRequest.getRequestUrl();
		}

		if(isSessionLogin() || isCookieLogin(request)) {
			savedRequest = WebUtils.getAndClearSavedRequest(request);
			if (savedRequest != null && savedRequest.getMethod().equalsIgnoreCase(AccessControlFilter.GET_METHOD)) {
				originUrl = savedRequest.getRequestUrl();
				return "redirect:"+originUrl;
			}
		}

		if(originUrl.startsWith("/admin")) {
			return "session/login";
		}else if(originUrl.startsWith("/cashier")){
			return "cashier/login";
		}else {
			//// TODO: 2016/10/20 for waiter login
			return "session/login";
		}
	}

	@RequestMapping(value = {"/login"}, method = RequestMethod.POST)
	@ResponseBody
	public Map<String, Object> create(@RequestBody Map<String, Object> userMap,
						 Model model,
						 HttpServletRequest request, HttpServletResponse response) {

		Map<String, Object> map = new HashMap<String, Object>();
		UserForm userForm = new UserForm();

		userForm.username =  userMap.get("username").toString();
		userForm.password = userMap.get("password").toString();
		String remember = userMap.get("remember").toString();

		Subject currentUser = SecurityUtils.getSubject();
		String md5Password = MD5Encode.encode(userForm.password);
		if(isCookieLogin(request)){
			map.put("valid", true);
			LOG.info("cookie login ");
			return map;
		}
		UsernamePasswordToken token = new UsernamePasswordToken(userForm.username, md5Password);
		LOG.info("login user "+userForm.username);
		try {
			currentUser.login(token);
			if (currentUser.isAuthenticated()) {
				map.put("valid", true);
				boolean remFlag = false;
				if(remember!=null && !remember.isEmpty())
				{
					remFlag = Boolean.parseBoolean(remember);
				}
                if(remFlag) {
					try {
						CookieUtil.setCookie(Constants.COOKIE_USER_KEY,  URLEncoder.encode(userForm.username,"UTF-8"), response);
						CookieUtil.setCookie(Constants.COOKIE_USERNAME, URLEncoder.encode(userForm.username,"UTF-8"), response);
					} catch (UnsupportedEncodingException e) {
						e.printStackTrace();
					}
					CookieUtil.setCookie(Constants.COOKIE_PASSWORD_KEY, md5Password, response);
					CookieUtil.setCookie(Constants.COOKIE_REMEMBER_ME, "1", response);
				}
			} else {
				map.put("valid", false);
				map.put("errorMsg", "用户名或密码错误！");
			}
		} catch (UnknownAccountException ex) {//用户名没有找到
			map.put("valid", false);
			map.put("errorMsg", "用户名或密码错误！");
		} catch (IncorrectCredentialsException ex) {//用户名密码不匹配
			map.put("valid", false);
			map.put("errorMsg", "用户名或密码错误！");
		} catch (AuthenticationException e) {
			e.printStackTrace();
			map.put("valid", false);
			map.put("errorMsg", "服务器异常，请稍后再试！");
		}

		UserModel user = (UserModel) ShiroRealmImpl.getSessionAttribute(Constants.SESSION_USER_KEY);
		if(user.kind.ordinal() ==3 ){
			map.put("url", "/admin/company");
		}
        if((Boolean)map.get("valid")==true) {
            SavedRequest savedRequest = WebUtils.getAndClearSavedRequest(request);
            if (savedRequest != null && savedRequest.getMethod().equalsIgnoreCase(AccessControlFilter.GET_METHOD)) {
                String saveUrl = savedRequest.getRequestUrl();
				map.put("url", saveUrl);
			}
			CookieUtil.setCookie(Constants.COOKIE_STORE_ID, String.valueOf(user.storeId),response);
			return map;
        }else {
            LOG.error("Login failed "+ map.get("errorMsg").toString());
            return map;
        }

	}

	@RequestMapping(value = {"/logout"}, method = RequestMethod.GET)
	public String logout(Model model, HttpServletResponse httpServletResponse) {
		Subject currentUser = SecurityUtils.getSubject();
		currentUser.logout();
		CookieUtil.deleteCookie(Constants.COOKIE_USER_KEY, httpServletResponse);
		CookieUtil.deleteCookie(Constants.COOKIE_PASSWORD_KEY, httpServletResponse);
		CookieUtil.deleteCookie(Constants.COOKIE_REMEMBER_ME, httpServletResponse);
		CookieUtil.deleteCookie(COOKIE_USERNAME,httpServletResponse);
		return "redirect:/login";
	}

	@RequestMapping(value = {"/cashier_login"}, method = RequestMethod.GET)
	public String front_logout(Model model, HttpServletResponse httpServletResponse) {
		Subject currentUser = SecurityUtils.getSubject();
		currentUser.logout();
		CookieUtil.deleteCookie(Constants.COOKIE_USER_KEY, httpServletResponse);
		CookieUtil.deleteCookie(Constants.COOKIE_PASSWORD_KEY, httpServletResponse);
		CookieUtil.deleteCookie(Constants.COOKIE_REMEMBER_ME, httpServletResponse);
		CookieUtil.deleteCookie(COOKIE_USERNAME,httpServletResponse);
		return "cashier/login";
	}
}
